/**
 * 
 */
package com.feonix.common.util;

import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.feonix.common.util.security.FileTypeChecker;

import net.lingala.zip4j.core.ZipFile;
import net.lingala.zip4j.exception.ZipException;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.ZipParameters;

/**
 * @CopyRight (c)1993-2017
 * @Project m-complat-common
 * @Comments 文件压缩工具类
 * @NameSpace com.feonix.common.util
 * @Author Feonixzw
 * @CreateDate 2017年11月28日
 */
public class ZipUtil {

	private static final Log logger = LogFactory.getLog(ZipUtil.class);

	/**
	 * 压缩
	 * 
	 * @param file
	 *            源文件/目录
	 * @param out
	 *            目标文件
	 */
	public static void zip(File file, File out) {
		if ((file == null) || (!file.exists())) {
			return;
		}
		try {
			ZipFile localZipFile = new ZipFile(out);
			localZipFile.setFileNameCharset("GBK");
			ZipParameters localZipParameters = new ZipParameters();
			zip(file, localZipFile, localZipParameters);
		} catch (ZipException localZipException) {
			logger.error("zip error", localZipException);
		}
	}

	/**
	 * 
	 * @param srcPath
	 *            源文件/目录
	 * @param outFilePath
	 *            目标文件
	 */
	public static void zip(String srcPath, String outFilePath) {
		File src = new File(srcPath);
		File out = new File(outFilePath);
		zip(src, out);
	}

	/**
	 * 
	 * @param file
	 *            源文件/目录
	 * @param out
	 *            输出文件
	 * @param defaultFolderPath
	 *            指定文件的路径
	 */
	public static void zip(File file, File out, String defaultFolderPath) {
		if ((file == null) || (!file.exists())) {
			return;
		}
		try {
			ZipFile zipFile = new ZipFile(out);
			zipFile.setFileNameCharset("GBK");
			ZipParameters zipParameters = new ZipParameters();
			zipParameters.setIncludeRootFolder(false);
			if (defaultFolderPath != null) {
				zipParameters.setDefaultFolderPath(defaultFolderPath);
			}
			zip(file, zipFile, zipParameters);
		} catch (ZipException localZipException) {
			logger.error("zip error", localZipException);
		}
	}

	/**
	 * 压缩
	 * 
	 * @param files
	 *            源文件/目录
	 * @param out
	 *            输出文件
	 */
	public static void zip(List<File> files, File out) {
		zip(files, out, null);
	}

	/**
	 * 压缩
	 * 
	 * @param files
	 *            源文件/目录
	 * @param out
	 *            输出文件
	 * @param defaultFolderPath
	 *            指定文件的路径
	 */
	public static void zip(List<File> files, File out, String defaultFolderPath) {
		if (CollectionUtils.isEmpty(files)) {
			return;
		}
		try {
			ZipFile zipFile = new ZipFile(out);
			zipFile.setFileNameCharset("GBK");
			ZipParameters zipParameters = new ZipParameters();
			if (defaultFolderPath != null) {
				zipParameters.setDefaultFolderPath(defaultFolderPath);
			}
			for (File localFile : files) {
				if ((localFile != null) && (localFile.exists())) {
					zip(localFile, zipFile, zipParameters);
				}
			}
		} catch (ZipException localZipException) {
			logger.error("zip error", localZipException);
		}
	}

	/**
	 * 压缩
	 * 
	 * @param files
	 *            源文件/目录
	 * @param out
	 *            输出文件
	 */
	public static void zip(File[] files, File out) {
		zip(files, out, null);
	}

	/**
	 * 压缩
	 * 
	 * @param files
	 *            源文件/目录
	 * @param out
	 *            输出文件
	 * @param defaultFolderPath
	 *            指定文件的路径
	 */
	public static void zip(File[] files, File out, String defaultFolderPath) {
		if (ArrayUtils.isEmpty(files)) {
			return;
		}
		try {
			ZipFile zipFile = new ZipFile(out);
			zipFile.setFileNameCharset("GBK");
			ZipParameters zipParameters = new ZipParameters();
			if (defaultFolderPath != null) {
				zipParameters.setDefaultFolderPath(defaultFolderPath);
			}
			File[] arrayOfFile = files;
			int j = files.length;
			for (int i = 0; i < j; i++) {
				File file = arrayOfFile[i];
				if ((file != null) && (file.exists())) {
					zip(file, zipFile, zipParameters);
				}
			}
		} catch (ZipException localZipException) {
			logger.error("zip error", localZipException);
		}
	}

	/**
	 * 压缩
	 * 
	 * @param file
	 * @param zipFile
	 * @param zipParameters
	 * @throws ZipException
	 */
	private static void zip(File file, ZipFile zipFile, ZipParameters zipParameters) throws ZipException {
		if (file.isDirectory()) {
			zipFile.addFolder(file, zipParameters);
		} else {
			zipFile.addFile(file, zipParameters);
		}
	}

	/**
	 * 解压缩、过滤危险文件，例如jsp等
	 * 
	 * @param file
	 *            压缩文件
	 * @param out
	 *            输出目录
	 */
	public static void unzip(File file, File out) {
		unzip(file, out, true);
	}

	/**
	 * 是否过滤危险文件，例如jsp等
	 * 
	 * @param file
	 *            压缩文件目录
	 * @param out
	 *            解压出的目录
	 * @param filte
	 *            是否过滤
	 */
	public static void unzip(File file, File out, boolean filte) {
		if ((file != null) && (out != null) && (file.exists()) && (!file.isDirectory())) {
			if (!out.exists()) {
				out.mkdirs();
			}
			try {
				ZipFile zipFile = new ZipFile(file);
				zipFile.setFileNameCharset("GBK");
				if (zipFile.isValidZipFile()) {
					if (filte) {
						List fileHeaders = zipFile.getFileHeaders();
						ArrayList vaildFiles = new ArrayList();
						String fileName;
						if (CollectionUtils.isNotEmpty(fileHeaders)) {
							fileName = null;
							for (Iterator iterator = fileHeaders.iterator(); iterator.hasNext();) {
								FileHeader fileHeader = (FileHeader) iterator.next();
								fileName = fileHeader.getFileName();
								if (!FileTypeChecker.valid(fileName)) {
									vaildFiles.add(fileName);
								}
							}
						}
						for (Iterator iterator = vaildFiles.iterator(); iterator.hasNext();) {
							fileName = StringUtil.getString(iterator.next());
							zipFile.removeFile(fileName);
						}
					}
					zipFile.extractAll(out.getAbsolutePath());
				}
			} catch (ZipException localZipException) {
				logger.error("unzip error", localZipException);
			}
		}
	}

	public static void unzip(String zipPath, String outPath) {
		unzip(zipPath, outPath, true);
	}

	public static void unzip(String zipPath, String outPath, boolean filte) {
		File inFile = new File(zipPath);
		File outFile = new File(outPath);
		unzip(inFile, outFile, filte);
	}

	/**
	 * 删除zip包中的文件
	 * 
	 * @param file
	 *            zip包
	 * @param fileName
	 *            要删除的文件
	 */
	public static void removeFile(File file, String fileName) {
		try {
			ZipFile localZipFile = new ZipFile(file);
			localZipFile.setFileNameCharset("GBK");
			localZipFile.removeFile(fileName);
		} catch (ZipException localZipException) {
			logger.error("removeFile error", localZipException);
		}
	}
}
